<template>
  <!-- 网络断开提示 -->
  <n-flex
    v-if="!isOnline"
    align="center"
    justify="center"
    class="z-999 absolute w-full h-40px rounded-4px text-(12px [--danger-text]) bg-[--danger-bg]">
    <svg class="size-16px"><use href="#cloudError"></use></svg>
    当前网络不可用，请检查你的网络设置
  </n-flex>

  <Transition name="chat-init" appear mode="out-in" @after-leave="handleTransitionComplete">
    <!-- 初次加载的骨架屏 -->
    <n-flex
      v-if="messageOptions?.isLoading && !messageOptions?.cursor"
      vertical
      :size="18"
      style="max-height: calc(100vh - 260px)"
      class="relative h-100vh box-border p-20px">
      <n-flex justify="end">
        <n-skeleton style="border-radius: 14px" height="40px" width="46%" :sharp="false" />
        <n-skeleton height="40px" circle />
      </n-flex>

      <n-flex>
        <n-skeleton height="40px" circle />
        <n-skeleton style="border-radius: 14px" height="60px" width="58%" :sharp="false" />
      </n-flex>

      <n-flex>
        <n-skeleton height="40px" circle />
        <n-skeleton style="border-radius: 14px" height="40px" width="26%" :sharp="false" />
      </n-flex>

      <n-flex justify="end">
        <n-skeleton style="border-radius: 14px" height="40px" width="60%" :sharp="false" />
        <n-skeleton height="40px" circle />
      </n-flex>
    </n-flex>

    <!-- 中间聊天内容(使用虚拟列表) -->
    <MessageList
      v-else
      id="image-chat-main"
      ref="messageListInst"
      :items="chatMessageList"
      :estimatedItemHeight="itemSize"
      :buffer="5"
      :isLoadingMore="messageOptions?.isLoading && isLoadingMore"
      :isLast="messageOptions?.isLast"
      @scroll="handleScroll"
      @scroll-direction-change="handleScrollDirectionChange"
      @loadMore="handleLoadMore"
      style="max-height: calc(100vh - 260px)">
      <template #default="{ item, index }">
        <n-flex
          vertical
          :key="index"
          class="flex-y-center"
          :class="[
            item.message.type === MsgEnum.RECALL ? 'min-h-22px' : 'min-h-62px',
            chatStore.isGroup ? 'p-[14px_20px]' : 'chat-single p-[4px_20px_10px_20px]',
            { 'active-reply': activeReply === item.message.id }
          ]">
          <!-- 信息间隔时间 -->
          <span class="text-(12px #909090) select-none p-4px" v-if="item.timeBlock">
            {{ item.timeBlock }}
          </span>

          <!--  消息为撤回消息  -->
          <div v-if="item.message.type === MsgEnum.RECALL">
            <template v-if="chatStore.isGroup">
              <n-flex align="center" :size="6" v-if="item.fromUser.uid === userUid">
                <p class="text-(12px #909090) select-none cursor-default">你撤回了一条消息</p>
                <p
                  v-if="canReEdit(item.message.id)"
                  class="text-(12px #13987f) select-none cursor-pointer"
                  @click="handleReEdit(item.message.id)">
                  重新编辑
                </p>
              </n-flex>
              <span v-else class="text-12px color-#909090 select-none" v-html="item.message.body"></span>
            </template>
            <template v-else>
              <n-flex align="center" :size="6">
                <p class="text-(12px #909090) select-none cursor-default">
                  {{ item.fromUser.uid === userUid ? '你撤回了一条消息' : '对方撤回了一条消息' }}
                </p>
                <p
                  v-if="canReEdit(item.message.id)"
                  class="text-(12px #13987f) select-none cursor-pointer"
                  @click="handleReEdit(item.message.id)">
                  重新编辑
                </p>
              </n-flex>
            </template>
          </div>

          <!-- 消息为系统消息时 -->
          <div v-else-if="item.message.type === MsgEnum.SYSTEM">
            <p class="text-(12px #909090) select-none cursor-default">
              {{ item.message.body }}
            </p>
          </div>

          <!-- 好友或者群聊的信息 -->
          <div
            v-else
            class="flex flex-col w-full"
            :class="[{ 'items-end': item.fromUser.uid === userUid }, chatStore.isGroup ? 'gap-18px' : 'gap-2px']">
            <!-- 信息时间(单聊) -->
            <div
              v-if="!chatStore.isGroup"
              class="text-(12px #909090) h-12px w-fit select-none"
              :class="
                item.fromUser.uid === userUid
                  ? activeReply === item.message.id
                    ? 'pr-68px'
                    : 'pr-42px'
                  : activeReply === item.message.id
                    ? 'pl-68px'
                    : 'pl-42px'
              ">
              <Transition name="fade-single">
                <span v-if="hoverBubble.key === item.message.id">
                  {{ formatTimestamp(item.message.sendTime, true) }}
                </span>
              </Transition>
            </div>
            <div class="flex items-start flex-1" :class="item.fromUser.uid === userUid ? 'flex-row-reverse' : ''">
              <!-- 回复消息提示的箭头 -->
              <svg
                v-if="activeReply === item.message.id"
                class="size-16px pt-4px color-#909090"
                :class="item.fromUser.uid === userUid ? 'ml-8px' : 'mr-8px'">
                <use :href="item.fromUser.uid === userUid ? `#corner-down-left` : `#corner-down-right`"></use>
              </svg>
              <!-- 头像  -->
              <n-popover
                @update:show="handlePopoverUpdate(item.message.id, $event)"
                trigger="click"
                placement="right"
                :show-arrow="false"
                v-model:show="infoPopover"
                style="padding: 0; background: var(--bg-info)">
                <template #trigger>
                  <ContextMenu
                    @select="$event.click(item, 'Main')"
                    :content="item"
                    :menu="chatStore.isGroup ? optionsList : void 0"
                    :special-menu="report">
                    <!-- 存在头像时候显示 -->
                    <n-avatar
                      round
                      :size="34"
                      @click="selectKey = item.message.id"
                      class="select-none"
                      :src="getAvatarSrc(item.fromUser.uid)"
                      :class="item.fromUser.uid === userUid ? '' : 'mr-10px'" />
                  </ContextMenu>
                </template>
                <!-- 用户个人信息框 -->
                <InfoPopover v-if="selectKey === item.message.id" :uid="item.fromUser.uid" />
              </n-popover>
              <n-flex
                vertical
                justify="center"
                :size="6"
                class="color-[--text-color] flex-1"
                :class="item.fromUser.uid === userUid ? 'items-end mr-10px' : ''">
                <n-flex
                  :size="4"
                  align="center"
                  :style="item.fromUser.uid === userUid ? 'flex-direction: row-reverse' : ''">
                  <ContextMenu
                    @select="$event.click(item, 'Main')"
                    :content="item"
                    :menu="chatStore.isGroup ? optionsList : void 0"
                    :special-menu="report">
                    <n-flex
                      :size="6"
                      class="select-none"
                      align="center"
                      v-if="chatStore.isGroup"
                      :style="item.fromUser.uid === userUid ? 'flex-direction: row-reverse' : ''">
                      <!-- 用户徽章 -->
                      <n-popover
                        v-if="
                          currentRoomId === '1' &&
                          useBadgeInfo(useUserInfo(item.fromUser.uid).value.wearingItemId).value.img
                        "
                        trigger="hover">
                        <template #trigger>
                          <img
                            class="size-18px"
                            :src="useBadgeInfo(useUserInfo(item.fromUser.uid).value.wearingItemId).value.img"
                            alt="badge" />
                        </template>
                        <span>{{
                          useBadgeInfo(useUserInfo(item.fromUser.uid).value.wearingItemId).value.describe
                        }}</span>
                      </n-popover>
                      <!-- 用户名 -->
                      <span class="text-12px select-none color-#909090 inline-block align-top">
                        {{ useUserInfo(item.fromUser.uid).value.name }}
                      </span>
                      <!-- 消息归属地 -->
                      <span class="text-(12px #909090)">
                        ({{ useUserInfo(item.fromUser.uid).value.locPlace || '未知' }})
                      </span>
                    </n-flex>
                  </ContextMenu>
                  <!-- 群主 -->
                  <div
                    v-if="chatStore.isGroup && groupStore.currentLordId === item.fromUser.uid"
                    class="flex p-4px rounded-4px bg-#f5dadf size-fit select-none">
                    <span class="text-(10px #d5304f)">群主</span>
                  </div>
                  <!-- 管理员 -->
                  <div
                    v-if="chatStore.isGroup && groupStore.adminUidList.includes(item.fromUser.uid)"
                    class="flex p-4px rounded-4px bg-#cef9ec size-fit select-none">
                    <span class="text-(10px #1a7d6b)">管理员</span>
                  </div>
                  <!-- 信息时间(群聊) -->
                  <Transition name="fade-group">
                    <span v-if="chatStore.isGroup && hoverBubble.key === item.message.id" class="text-(12px #909090)">
                      {{ formatTimestamp(item.message.sendTime, true) }}
                    </span>
                  </Transition>
                </n-flex>
                <!--  气泡样式  -->
                <ContextMenu
                  :content="item"
                  @contextmenu="handleMacSelect"
                  @mouseenter="handleMouseEnter(item.message.id)"
                  @mouseleave="handleMouseLeave"
                  class="w-fit relative flex flex-col"
                  :data-key="item.fromUser.uid === userUid ? `U${item.message.id}` : `Q${item.message.id}`"
                  :class="item.fromUser.uid === userUid ? 'items-end' : 'items-start'"
                  :style="{ '--bubble-max-width': chatStore.isGroup ? '32vw' : '50vw' }"
                  @select="$event.click(item)"
                  :menu="handleItemType(item.message.type)"
                  :emoji="chatStore.isGroup ? emojiList : []"
                  :special-menu="specialMenuList"
                  @reply-emoji="handleEmojiSelect($event.label, item)"
                  @click="handleMsgClick(item)">
                  <!-- 渲染消息内容体 TODO: 等完善消息类型后逐渐替换使用RenderMessage -->
                  <RenderMessage
                    :class="[
                      { active: activeBubble === item.message.id },
                      item.message.type !== MsgEnum.IMAGE
                        ? item.fromUser.uid === userUid
                          ? 'bubble-oneself'
                          : 'bubble'
                        : ''
                    ]"
                    :message="item.message" />

                  <!-- 显示翻译文本 -->
                  <Transition name="fade-translate" appear mode="out-in">
                    <div
                      v-if="item.message.body.translatedText"
                      class="translated-text select-none cursor-default flex flex-col"
                      :class="[item.fromUser.uid === userUid ? 'item-end' : 'item-start']">
                      <n-flex align="center" justify="space-between" class="mb-6px">
                        <n-flex align="center" :size="4">
                          <span class="text-(12px #909090)">{{ item.message.body.translatedText.provider }}</span>
                          <svg class="size-12px"><use href="#success"></use></svg>
                        </n-flex>
                        <svg class="size-10px cursor-pointer" @click="item.message.body.translatedText = null">
                          <use href="#close"></use>
                        </svg>
                      </n-flex>
                      <p class="select-text cursor-text">{{ item.message.body.translatedText.text }}</p>
                    </div>
                  </Transition>

                  <!--  消息为为图片类型(不固定宽度和高度), 多张图片时渲染  -->
                  <!-- <n-image-group v-if="Array.isArray(item.message.body.url) && item.message.type === MsgEnum.IMAGE">
                    <n-flex class="photo-wall" vertical>
                      <n-image
                        class="select-none"
                        v-for="(src, index) in item.message.body.url"
                        :key="index"
                        :img-props="{ style: { maxWidth: '325px', maxHeight: '165px', width: '100%', height: 'auto' } }"
                        show-toolbar-tooltip
                        style="border-radius: 8px"
                        :fallback-src="'https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg'"
                        :src="src"></n-image>
                    </n-flex>
                  </n-image-group> -->

                  <!-- 消息为文件 -->
                  <n-image
                    class="select-none"
                    v-if="typeof item.message.body.url === 'string' && item.message.type === MsgEnum.FILE"
                    :img-props="{ style: { maxWidth: '325px', maxHeight: '165px' } }"
                    show-toolbar-tooltip
                    preview-disabled
                    style="border-radius: 8px"
                    :src="item.message.body.url"></n-image>
                  <!-- 消息状态指示器 -->
                  <div v-if="item.fromUser.uid === userUid" class="absolute -left-6 top-2">
                    <n-icon v-if="item.message.status === MessageStatusEnum.SENDING" class="text-gray-400">
                      <img class="size-16px" src="@/assets/img/loading-one.svg" alt="" />
                    </n-icon>
                    <n-icon
                      v-if="item.message.status === MessageStatusEnum.FAILED"
                      class="text-#d5304f cursor-pointer"
                      @click.stop="handleRetry(item)">
                      <svg class="size-16px"><use href="#cloudError"></use></svg>
                    </n-icon>
                  </div>
                </ContextMenu>

                <!-- 回复的内容 -->
                <n-flex
                  align="center"
                  :size="6"
                  v-if="item.message.body.reply"
                  @click="jumpToReplyMsg(item.message.body.reply.id)"
                  class="reply-bubble relative w-fit custom-shadow">
                  <svg class="size-14px">
                    <use href="#to-top"></use>
                  </svg>
                  <n-avatar class="reply-avatar" round :size="20" :src="getAvatarSrc(item.message.body.reply.uid)" />
                  <span>{{ `${item.message.body.reply.username}：` }}</span>
                  <span class="content-span">
                    {{ item.message.body.reply.body }}
                  </span>
                  <div v-if="item.message.body.reply.imgCount" class="reply-img-sub">
                    {{ item.message.body.reply.imgCount }}
                  </div>
                </n-flex>

                <!-- 群聊回复emoji表情 -->
                <n-flex :size="4" v-if="chatStore.isGroup && item.emojiList">
                  <n-flex
                    :size="2"
                    align="center"
                    class="emoji-reply-bubble"
                    @click.stop="cancelReplyEmoji(item, index)"
                    v-for="(emoji, index) in item.emojiList"
                    :key="index">
                    {{ emoji.label }}
                    <span class="text-(12px #eee)">{{ emoji.count }}</span>
                  </n-flex>
                </n-flex>
              </n-flex>
            </div>
          </div>
        </n-flex>
      </template>
    </MessageList>
  </Transition>

  <!-- 弹出框 -->
  <n-modal v-model:show="modalShow" class="w-350px border-rd-8px">
    <div class="bg-[--bg-popover] w-360px h-full p-6px box-border flex flex-col">
      <div
        v-if="type() === 'macos'"
        @click="modalShow = false"
        class="mac-close z-999 size-13px shadow-inner bg-#ed6a5eff rounded-50% select-none absolute left-6px">
        <svg class="hidden size-7px color-#000 font-bold select-none absolute top-3px left-3px">
          <use href="#close"></use>
        </svg>
      </div>

      <svg v-if="type() === 'windows'" @click="modalShow = false" class="w-12px h-12px ml-a cursor-pointer select-none">
        <use href="#close"></use>
      </svg>
      <div class="flex flex-col gap-30px p-[22px_10px_10px_22px] select-none">
        <span class="text-14px">{{ tips }}</span>

        <n-flex justify="end">
          <n-button @click="handleConfirm" class="w-78px" color="#13987f">确定</n-button>
          <n-button @click="modalShow = false" class="w-78px" secondary>取消</n-button>
        </n-flex>
      </div>
    </div>
  </n-modal>

  <!--  悬浮按钮提示(底部悬浮) -->
  <footer
    class="float-footer"
    v-if="floatFooter && currentNewMsgCount?.count && currentNewMsgCount.count > 0"
    :class="chatStore.isGroup ? 'right-220px' : 'right-50px'">
    <div class="float-box" :class="{ max: currentNewMsgCount?.count > 99 }" @click="scrollBottom">
      <n-flex justify="space-between" align="center">
        <n-icon :color="currentNewMsgCount?.count > 99 ? '#ce304f' : '#13987f'">
          <svg><use href="#double-down"></use></svg>
        </n-icon>
        <span class="text-12px" :class="{ 'color-#ce304f': currentNewMsgCount?.count > 99 }">
          {{ currentNewMsgCount?.count > 99 ? '99+' : currentNewMsgCount?.count }}条新消息
        </span>
      </n-flex>
    </div>
  </footer>
</template>
<script setup lang="ts">
import { EventEnum, MittEnum, MsgEnum, MessageStatusEnum } from '@/enums'
import { type MessageType, SessionItem } from '@/services/types.ts'
import { useMitt } from '@/hooks/useMitt.ts'
import { usePopover } from '@/hooks/usePopover.ts'
import { useWindow } from '@/hooks/useWindow.ts'
import { useChatMain } from '@/hooks/useChatMain.ts'
import { delay } from 'lodash-es'
import { formatTimestamp } from '@/utils/ComputedTime.ts'
import { useUserInfo, useBadgeInfo } from '@/hooks/useCached.ts'
import { useChatStore } from '@/stores/chat.ts'
import { type } from '@tauri-apps/plugin-os'
import { useUserStore } from '@/stores/user.ts'
import { useNetwork } from '@vueuse/core'
import { AvatarUtils } from '@/utils/AvatarUtils'
import MessageList, { type MessageListExpose } from '@/components/common/MessageList.vue'
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
import { useTauriListener } from '@/hooks/useTauriListener'
import { useGroupStore } from '@/stores/group.ts'
import { useGlobalStore } from '@/stores/global'
import { useDebounceFn } from '@vueuse/core'

const appWindow = WebviewWindow.getCurrent()
const { addListener } = useTauriListener()
const props = defineProps<{
  activeItem: SessionItem
}>()
const activeItemRef = shallowRef<SessionItem>(props.activeItem)
const chatStore = useChatStore()
const userStore = useUserStore()
const groupStore = useGroupStore()
const globalStore = useGlobalStore()

// 记录当前滚动位置相关信息
const isAutoScrolling = ref(false)

/** 记录是否正在向上滚动 */
const isScrollingUp = ref(false)
// 添加标记，用于识别是否正在加载历史消息
const isLoadingMore = ref(false)

const userUid = computed(() => userStore.userInfo.uid)
const chatMessageList = computed(() => chatStore.chatMessageList)
const currentNewMsgCount = computed(() => chatStore.currentNewMsgCount)
const messageOptions = computed(() => chatStore.currentMessageOptions)
const { createWebviewWindow } = useWindow()
const currentRoomId = computed(() => globalStore.currentSession?.roomId)
/** 是否是超级管理员 */
// const isAdmin = computed(() => userInfo?.power === PowerEnum.ADMIN)
/** 跳转回复消息后选中效果 */
const activeReply = ref('')
/** item最小高度，用于计算滚动大小和位置 */
const itemSize = computed(() => (chatStore.isGroup ? 90 : 76))
/** 虚拟列表 */
const messageListInst = useTemplateRef<MessageListExpose>('messageListInst')
/** 手动触发Popover显示 */
const infoPopover = ref(false)
// 记录 requestAnimationFrame 的返回值
const rafId = ref<number>()
/** 鼠标悬浮的气泡显示对应的时间 */
const hoverBubble = ref<{
  key: number
  timer?: NodeJS.Timeout
}>({
  key: -1
})
/** 记录右键菜单时选中的气泡的元素(用于处理mac右键会选中文本的问题) */
const recordEL = ref()
/** 网络连接是否正常 */
const { isOnline } = useNetwork()
const isMac = computed(() => type() === 'macos')
const {
  handleMsgClick,
  handleConfirm,
  handleItemType,
  activeBubble,
  floatFooter,
  tips,
  modalShow,
  specialMenuList,
  optionsList,
  report,
  selectKey,
  emojiList,
  scrollTop
} = useChatMain()
const { handlePopoverUpdate, enableScroll } = usePopover(selectKey, 'image-chat-main')
provide('popoverControls', { enableScroll })

// 添加防抖处理
const debouncedScrollToBottom = useDebounceFn(() => {
  if (!messageListInst.value) return
  messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
}, 100)

// 监听会话切换
watch(
  () => props.activeItem,
  (value, oldValue) => {
    if (oldValue.roomId !== value.roomId) {
      // 使用防抖的滚动处理
      debouncedScrollToBottom()
    }
  }
)

// 监听消息列表变化
watch(
  chatMessageList,
  (value, oldValue) => {
    // 确保消息属于当前会话
    if (!value.length || (value[0] && value[0].message.roomId !== props.activeItem.roomId)) {
      return
    }

    if (value.length > oldValue.length) {
      // 获取最新消息
      const latestMessage = value[value.length - 1]

      // 如果正在加载历史消息，优先处理历史消息的滚动
      if (isLoadingMore.value) {
        if (scrollTop.value < 26) {
          requestAnimationFrame(() => {
            messageListInst.value?.scrollTo({ index: value.length - oldValue.length })
          })
        }
        return
      }

      // 优先级1：用户发送的消息，始终滚动到底部
      if (latestMessage?.fromUser?.uid === userUid.value) {
        messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
        return
      }

      // 优先级2：已经在底部时的新消息
      const container = messageListInst.value?.getContainer()
      if (container) {
        const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight
        if (distanceFromBottom <= 300) {
          messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
          return
        }

        // 其他情况：如果是他人的消息且不在底部，增加新消息计数
        if (latestMessage?.fromUser?.uid !== userUid.value) {
          const current = chatStore.newMsgCount.get(props.activeItem.roomId)
          if (!current) {
            chatStore.newMsgCount.set(props.activeItem.roomId, {
              count: 1,
              isStart: true
            })
          } else {
            current.count++
          }
        }
      }
    }
  },
  { deep: false }
)

/** 处理滚动方向变化 */
const handleScrollDirectionChange = (direction: 'up' | 'down') => {
  isScrollingUp.value = direction === 'up'
}

/** 处理滚动事件(用于页脚显示功能) */
const handleScroll = () => {
  if (isAutoScrolling.value) return // 如果是自动滚动，不处理
  const container = messageListInst.value?.getContainer()
  if (!container) return

  // 获取已滚动的距离
  scrollTop.value = container.scrollTop
  // 获取整个滚动容器的高度
  const scrollHeight = container.scrollHeight
  // 获取容器的可视区域高度
  const clientHeight = container.clientHeight
  // 计算距离底部的距离
  const distanceFromBottom = scrollHeight - scrollTop.value - clientHeight

  // 存储 requestAnimationFrame 的返回值
  rafId.value = requestAnimationFrame(async () => {
    // 处理触顶加载更多
    if (scrollTop.value < 26) {
      // 如果正在加载或已经触发了加载，则不重复触发
      if (messageOptions.value?.isLoading || isLoadingMore.value) return

      // 记录当前的内容高度
      const oldScrollHeight = container.scrollHeight

      isLoadingMore.value = true
      // 禁用滚动交互但保持滚动条显示
      container.style.pointerEvents = 'none'
      await new Promise((resolve) => setTimeout(resolve, 300))
      await chatStore.loadMore()
      // 加载完成后，计算新增内容的高度差，并设置滚动位置
      nextTick(() => {
        const newScrollHeight = container.scrollHeight
        const heightDiff = newScrollHeight - oldScrollHeight
        if (heightDiff > 0) {
          container.scrollTop = heightDiff
        }
        // 恢复滚动交互
        nextTick(() => {
          container.style.pointerEvents = 'auto'
          isLoadingMore.value = false
        })
      })
    }

    // 处理底部滚动和新消息提示
    if (distanceFromBottom <= 20) {
      floatFooter.value = false
      chatStore.clearNewMsgCount()
    } else {
      floatFooter.value = true
    }
  })
}

/** 处理过渡动画完成后的滚动 */
const handleTransitionComplete = () => {
  if (!messageOptions.value?.isLoading) {
    nextTick(() => {
      messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
    })
  }
}

/** 获取用户头像 */
const getAvatarSrc = (uid: string) => {
  const avatar = uid === userUid.value ? userStore.userInfo.avatar : useUserInfo(uid).value.avatar
  return AvatarUtils.getAvatarUrl(avatar as string)
}

// 当鼠标进入时触发的处理函数
const handleMouseEnter = (key: any) => {
  hoverBubble.value.timer = setTimeout(() => {
    hoverBubble.value.key = key
  }, 1600)
}

// 当鼠标离开时触发的处理函数
const handleMouseLeave = () => {
  // 如果定时器存在，则清除定时器并重置为undefined
  if (hoverBubble.value.timer) {
    clearTimeout(hoverBubble.value.timer)
    hoverBubble.value.timer = void 0
  }
  // 重置悬浮气泡的key值为-1
  hoverBubble.value.key = -1
}

/** 取消回复emoji表情 */
const cancelReplyEmoji = (item: any, index: number) => {
  // 判断item.emojiList数组中的count是否为1，如果为1则删除该元素，否则count-1
  if (item.emojiList[index].count === 1) {
    item.emojiList.splice(index, 1)
  } else {
    item.emojiList[index].count--
  }
}

/** 处理emoji表情回应 */
const handleEmojiSelect = (label: string, item: any) => {
  if (!item.emojiList) {
    item.emojiList = [{ label: label, count: 1 }]
  } else {
    // 比较label是否存在，存在则计数+1，不存在则新增
    const index = item.emojiList.findIndex((item: any) => item.label === label)
    if (index > -1) {
      item.emojiList[index].count++
    } else {
      item.emojiList.push({ label: label, count: 1 })
    }
  }
}

// /** 处理回复消息中的 AIT 标签 */
// const handleReply = (content: string) => {
//   return content.includes('id="aitSpan"') ? removeTag(content) : content
// }

/** 跳转到回复消息 */
const jumpToReplyMsg = (key: string) => {
  nextTick(() => {
    // 找到对应消息的索引
    const messageIndex = chatMessageList.value.findIndex((msg) => msg.message.id === key)
    if (messageIndex !== -1) {
      messageListInst.value?.scrollTo({ index: messageIndex, behavior: 'instant' })
      activeReply.value = key
    }
  })
}

/**
 * 给气泡添加动画
 * @param index 下标
 * @param id 用户ID
 */
const addToDomUpdateQueue = (index: string, id: string) => {
  // 使用 nextTick 确保虚拟列表渲染完最新的项目后进行滚动
  nextTick(() => {
    /** data-key标识的气泡,添加前缀用于区分用户消息，不然气泡动画会被覆盖 */
    const dataKey = id === userUid.value ? `U${index}` : `Q${index}`
    const lastMessageElement = document.querySelector(`[data-key="${dataKey}"]`) as HTMLElement
    if (lastMessageElement) {
      // 添加动画类
      lastMessageElement.classList.add('bubble-animation')
      // 监听动画结束事件
      const handleAnimationEnd = () => {
        lastMessageElement.classList.remove('bubble-animation')
        lastMessageElement.removeEventListener('animationend', handleAnimationEnd)
      }
      lastMessageElement.addEventListener('animationend', handleAnimationEnd)
    }
  })
}

/** 点击后滚动到底部 */
const scrollBottom = () => {
  if (!messageListInst.value) return

  nextTick(() => {
    messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
  })
}

/**
 * 解决mac右键会选中文本的问题
 * @param event
 */
const handleMacSelect = (event: any) => {
  if (isMac.value) {
    event.target.classList.add('select-none')
    recordEL.value = event.target
  }
}

const closeMenu = (event: any) => {
  if (!event.target.matches('.bubble', 'bubble-oneself')) {
    activeBubble.value = ''
    // 解决mac右键会选中文本的问题
    if (isMac.value && recordEL.value) {
      recordEL.value.classList.remove('select-none')
    }
  }
  if (!event.target.matches('.active-reply')) {
    /** 解决更替交换回复气泡时候没有触发动画的问题 */
    if (!event.target.matches('.reply-bubble *')) {
      nextTick(() => {
        const activeReplyElement = document.querySelector('.active-reply') as HTMLElement
        if (activeReplyElement) {
          activeReplyElement.classList.add('reply-exit')
          delay(() => {
            activeReplyElement.classList.remove('reply-exit')
            activeReply.value = ''
          }, 300)
        }
      })
    }
  }
}

const handleRetry = (item: any) => {
  // TODO: 实现重试发送逻辑
  console.log('重试发送消息:', item)
}

const canReEdit = computed(() => (msgId: string) => {
  const recalledMsg = chatStore.getRecalledMessage(msgId)
  const message = chatStore.getMessage(msgId)
  if (!recalledMsg || !message) return false

  // 只需要判断是否是当前用户的消息，时间检查已经在 getRecalledMessage 中处理
  return message.fromUser.uid === userUid.value
})

const handleReEdit = (msgId: string) => {
  const recalledMsg = chatStore.getRecalledMessage(msgId)
  if (recalledMsg) {
    useMitt.emit(MittEnum.RE_EDIT, recalledMsg.content)
  }
}

// 处理加载更多
const handleLoadMore = async () => {
  // 如果正在加载或已经触发了加载，则不重复触发
  if (messageOptions.value?.isLoading || isLoadingMore.value) return

  // 记录当前的内容高度
  const container = messageListInst.value?.getContainer()
  if (!container) return
  const oldScrollHeight = container.scrollHeight

  isLoadingMore.value = true
  // 禁用滚动交互但保持滚动条显示
  container.style.pointerEvents = 'none'
  await new Promise((resolve) => setTimeout(resolve, 300))
  await chatStore.loadMore()

  // 加载完成后，计算新增内容的高度差，并设置滚动位置
  nextTick(() => {
    const newScrollHeight = container.scrollHeight
    const heightDiff = newScrollHeight - oldScrollHeight
    if (heightDiff > 0) {
      container.scrollTop = heightDiff
    }
    // 恢复滚动交互
    nextTick(() => {
      container.style.pointerEvents = 'auto'
      isLoadingMore.value = false
    })
  })
}

onMounted(async () => {
  nextTick(() => {
    messageListInst.value?.scrollTo({ position: 'bottom', behavior: 'instant' })
  })
  useMitt.on(MittEnum.MESSAGE_ANIMATION, async (messageType: MessageType) => {
    addToDomUpdateQueue(messageType.message.id, messageType.fromUser.uid)
  })
  useMitt.on(`${MittEnum.INFO_POPOVER}-Main`, (event: any) => {
    selectKey.value = event.uid
    infoPopover.value = true
    handlePopoverUpdate(event.uid)
  })
  useMitt.on(MittEnum.MSG_BOX_SHOW, (event: any) => {
    activeItemRef.value = event.item
  })
  await addListener(
    appWindow.listen(EventEnum.SHARE_SCREEN, async () => {
      await createWebviewWindow('共享屏幕', 'sharedScreen', 840, 840)
    })
  )
  window.addEventListener('click', closeMenu, true)
})

onUnmounted(() => {
  if (rafId.value) {
    cancelAnimationFrame(rafId.value)
  }
  if (hoverBubble.value.timer) {
    clearTimeout(hoverBubble.value.timer)
    hoverBubble.value.timer = void 0
  }
  hoverBubble.value.key = -1
  window.removeEventListener('click', closeMenu, true)
})
</script>

<style scoped lang="scss">
@use '@/styles/scss/chat-main';
</style>
